package connection;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;
//import java.util.concurrent.CopyOnWriteArrayList;

public class IrcConnection {
	String server;
	int port;
	BufferedReader in;
	BufferedWriter out;
	Socket sock;
	HashMap<String, ArrayList<IrcFunction>> eventListeners;
	String[] nickname = {"helltest", "trymeonce"};
	int nickIndex=0;
	boolean arrayBusy;
	
	
	public IrcConnection(String host, int port) {
		arrayBusy=false;
		server = host;
		this.port = port;
		eventListeners = new HashMap<String, ArrayList<IrcFunction>>();
	}
	
	public void connect() {
		try {
			sock = new Socket(server, port);
			in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
			out = new BufferedWriter(new OutputStreamWriter(sock.getOutputStream()));
			new Thread(new MessageReciever(in)).start();
		} catch (IOException e) {
			e.printStackTrace();
		}
		query("USER test ing this :shit");
		query("NICK "+ nickname[0]);
	}
	
	public void query(String msg) {
		if (!msg.endsWith("\n")) {
			msg += "\n";
		}
		try {
			out.write(msg);
			out.flush();
			System.out.print("> "+ msg);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public void privMsg(String target, String msg) {
		query("PRIVMSG "+ target +" :"+msg);
	}
	public void join(String channel) {
		if (channel.indexOf(':') == -1) {
			query("JOIN "+channel);
		} else {
			String[] tmp=channel.split(":");
			query("JOIN "+tmp[0]+" "+tmp[1]);
		}
	}
	public void setTopic(String target, String topic) {
		query("TOPIC "+ target +" :"+ topic);
	}
	public void quit(String reason) {
		query("QUIT "+reason);
	}
	public void quit() {
		query("QUIT");
	}
	
	private boolean parseMsg(String message) {
		System.out.println("< "+ message);
		String cmd = message.split(" ", 2)[1];
		if (message.startsWith("PING ")) {
			query("PONG "+ message.substring(5));
			return true;
		} else if (cmd.equals("433")) {
			if (++nickIndex < nickname.length)
				query("NICK "+nickname[nickIndex]);
			return true;
		}
		return false;
	}
	
	public void addEventListener(IrcFunction a, String command) {
		/*while (arrayBusy) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}*/
		if (!eventListeners.containsKey(command)) {
			eventListeners.put(command, new ArrayList<IrcFunction>());
		}
		eventListeners.get(command).add(a);
	}
	
	public void removeEventListener(IrcFunction func) {

		for (ArrayList<IrcFunction> arr: eventListeners.values()) {
			System.out.println(arr.toString());
			if (arr.contains(func)) {
				System.out.println("true");
				arr.remove(func);
			}
		}
		
	}
	private void debug(int level, String message) {
		System.out.println(message);
	}
	private class MessageReciever implements Runnable {
		BufferedReader in;
		
		public MessageReciever(BufferedReader inStream) {
			in = inStream;
		}
		
		public void run() {
			String[] inLine = new String[3];
			try {
				while (true) {
					inLine[0] = in.readLine();
					if (!parseMsg(inLine[0])) {
						//arrayBusy=true;
						inLine = inLine[0].split(" ", 3);
					
						ArrayList<IrcFunction> functionsAL = eventListeners.get(inLine[1]);
						
						if (functionsAL != null) {
							ArrayList<IrcFunction> functions = (ArrayList<IrcFunction>) functionsAL.clone();
							IrcEvent event = new IrcEvent(this, inLine);
							for (IrcFunction a: functions) {
								try {
									a.eventPerformed(event);
								} catch (Exception e) {
									debug(1, "removed eventlistener: "+ a.toString());
									removeEventListener(a);
								}
							}
						}
						//arrayBusy=false;
					}
				}
			} catch (IOException e) {
			}
		}
	}


}
